/*
 * @Author: 鱿鱼溪学院
 * @Date: 2025-04-22 00:11:35
 * @LastEditTime: 2025-04-22 23:43:45
 * @LastEditors: 鱿鱼溪学院
 * @Description:
 * @FilePath: \yyx_ser_ts\utils\aes.ts
 * Copyright 鱿鱼溪学院 by edu v1.0
 * 天道酬勤
 */

import CryptoJS from 'crypto-js'
import { crpytException } from '../app/exception/HttpException'

// 定义加密密钥
const key = CryptoJS.enc.Utf8.parse('1234123412ABCDEF') // 解析密钥
// 定义加密初始向量
const iv = CryptoJS.enc.Utf8.parse('ABCDEF1234123412') // 解析初始向量

/**
 * 加密方法
 * 使用AES加密算法，CBC模式，Pkcs7填充方式
 * @param word 需要加密的明文
 * @returns 返回加密后的密文，以十六进制字符串形式表示
 */
export const encrypt = (word: string) => {
  if (!word) {
    throw new crpytException([], '明文不能为空')
  }

  let srcs = CryptoJS.enc.Utf8.parse(word)
  const encrypted = CryptoJS.AES.encrypt(srcs, key, {
    iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })
  return encrypted.ciphertext.toString().toUpperCase()
}

/**
 * 解密给定的字符串
 * 该函数首先验证输入字符串是否为有效的十六进制格式，然后将其转换为WordArray对象，
 * 再使用AES解密器进行解密，最后将解密后的数据转换为UTF-8字符串返回
 *
 * @param word 待解密的十六进制字符串
 * @returns 解密后的UTF-8字符串
 * @throws 如果输入字符串无效或解密过程失败，则抛出错误
 */
export const decrypt = (word: string) => {
  if (!word) {
    throw new crpytException([], '输入不能为空')
  }
  // 检查输入是否为有效的十六进制字符串
  if (!/^[0-9A-Fa-f]+$/.test(word)) {
    //  throw new UserValidationException('', 'aaaa!', 20001)
    // throw new Error('Invalid hexadecimal string')
    throw new crpytException([], '无效的十六进制字符串')
  }

  // 当密文以十六进制格式存储时，需先用此方法将其转为WordArray，再传递给解密函数‌。
  let encryptedHexStr = CryptoJS.enc.Hex.parse(word)

  // 将WordArray转换为Base64字符串，以便AES解密器可以处理
  let srcs = CryptoJS.enc.Base64.stringify(encryptedHexStr)

  // 使用AES进行解密，需要指定密钥和初始化向量（iv），并配置解密模式和填充方式
  const decrypted = CryptoJS.AES.decrypt(srcs, key, {
    iv,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  })

  // 将解密后的数据转换为UTF-8字符串
  let decryptedStr = decrypted.toString(CryptoJS.enc.Utf8)

  // 检查解密后的字符串是否为空或无效
  if (!decryptedStr) {
    throw new crpytException([], '解密过程失败')
  }

  // 返回解密后的字符串
  return decryptedStr.toString()
}
